#include <GameEngine/UnitTest/unit_test.h>

#include <GameEngine/Core/Graph/graph_node.h>
#include <GameEngine/Core/Graph/graph_link.h>
#include <GameEngine/Core/Graph/graph.h>


#ifdef GAMEENGINE_NAMESPACES
namespace GameEngine {
#endif


//! Typedef used for the portability of the unit test
typedef GameEngine::GraphNode< int > Node;
//! Typedef used for the portability of the unit test
typedef GameEngine::GraphLink< Node, float > Link;

//! Launch the unit tests on graph lists
/*!
 @return True if all unit tests on graph lists were
         succesful, false otherwise
 */
bool UnitTest::test_core_graph_functions() {
	bool res = true;

	// Get number of bytes
	MemoryManager::BytesCount bytes = MemoryManager::instance()->bytes();

	// Create graph
	GameEngine::Graph< Node, Link > initial_graph;
	Node n(0);
	Node* prev = initial_graph.add_node(n);
	res &= UNIT_TEST_ERROR( "[Graph] Add node", ( prev != nil ) );
	Node* first = nil;
	Link l;
	Link* first_lnk = nil;
	for ( int k = 1; k < 5; ++k ) {
		n = Node(k);
		Node* next = initial_graph.add_node(n);
		res &= UNIT_TEST_ERROR( "[Graph] Add node", ( next != nil ) );
		l = Link(k,prev,next);
		prev = next;
		if ( first == nil ) first = prev;
		Link* lnk = initial_graph.add_link(l);
		if ( first_lnk == nil ) first_lnk = lnk;
		res &= UNIT_TEST_ERROR( "[Graph] Add link", ( lnk != nil ) );
	}

	// Copy constructor
	GameEngine::Graph< Node, Link > graph = initial_graph;

	// Check links
	Node* fst = graph.find_node(*first);
	GameEngine::Graph< Node, Link >::LinkSet links = graph.links(fst);
	{{
		res &= UNIT_TEST_ERROR( "[Graph] Get links from node", ( links.size() == 2 ) );
		int val1 = 0, val2 = 0, val_other = 0;
		for ( GameEngine::Graph< Node, Link >::LinkSet::iterator it = links.begin(); it != links.end(); ++it ) {
			int val = (*it)->value();
			if ( val == 1 ) ++val1;
			else if ( val == 2 ) ++val2;
			else ++val_other;
		}
		res &= UNIT_TEST_ERROR( "[Graph] Get links from node, check value", ( val1 == 1 ) );
		res &= UNIT_TEST_ERROR( "[Graph] Get links from node, check value", ( val2 == 1 ) );
		res &= UNIT_TEST_ERROR( "[Graph] Get links from node, check value", ( val_other == 0 ) );
	}}

	// Remove links from node
	graph.remove_links(n);
	links = graph.links(prev);
	res &= UNIT_TEST_ERROR( "[Graph] Remove links from node", ( links.size() == 0 ) );

	// Remove links from link
	int rem_value = 3;
	Link* lnk_rem = graph.find_link(Link(rem_value));
	const Node* node_rem = lnk_rem->node1();
	res &= UNIT_TEST_ERROR( "[Graph] Remove links from link", ( graph.remove_link(*lnk_rem) ) );
	links = graph.links(node_rem);
	for ( GameEngine::Graph< Node, Link >::LinkSet::iterator it = links.begin(); it != links.end(); ++it ) {
		res &= UNIT_TEST_ERROR( "[Graph] Get links from link, check values", ( (*it)->value() != rem_value ) );
	}

	// Get number of bytes
	res &= UNIT_TEST_ERROR( "[Graph] Test memory leak", ( bytes == MemoryManager::instance()->bytes() ));

	// Return result
	return res;
}


#ifdef GAMEENGINE_NAMESPACES
} // namespace GameEngine
#endif
